
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#define IR			(1 << 3)
#define UV			(1 << 4)
#define LASER		(1 << 5)
#define RED			(1 << 2)
#define GREEN		(1 << 1)
#define BLUE		(1 << 0)
#define REDS		(1 << 0)
#define GREENS		(1 << 2)
#define BLUES		(1 << 1)
#define REDS2		(1 << 6)

uint8_t data[3];
uint8_t adress;

uint8_t power[4];
uint8_t pin[3];

uint8_t S = 20;
uint8_t i = 0;
uint8_t j;

uint8_t num = 0;

uint8_t iBlink = 0;
uint8_t led0 = 0;
uint8_t aud0 = 0;

uint8_t onState = 0;
uint8_t mode = 1;
uint8_t strob = 0;

uint8_t backUp = 0;

uint8_t phase = 0;

static uint8_t led_blink(uint8_t numBlink){
  for(i=1;i<=numBlink*2;i++) {
    PORTD ^= IR;
    _delay_ms(60);
  }
  return 0;
}

ISR(TIMER2_OVF_vect) {
  if (onState) {
    if(!strob) {
      if(power[0] > 3)
	PORTD |= pin[0];
      if(power[1] > 3)
	PORTD |= pin[1];
      if(power[2] > 3)
	PORTD |= pin[2];
    }
    else {
      if(phase < S) {
	if(power[0] > 3)
	  PORTD ^= pin[0];
	if(power[1] > 3)
	  PORTD ^= pin[1];
	if(power[2] > 3)
	  PORTD ^= pin[2];
      }
      phase += 1;
    }
  }
  num = 0;
  OCR2 = power[num];
}

ISR(TIMER2_COMP_vect) {
  PORTD &= ~pin[num];
  if(num < 2) {
    num++;
    OCR2 = power[num];
  }
  else
    OCR2 = 0xFF;
}

int main(void){	
	
	cli();
	TIMSK |= (1 << TOIE2)|(1 << OCIE2); // overflow interrupt by timer 2 and 0

	
	TCCR2 |= (1 << CS22); // by 32
	/* **********************************
	 *               PORTS ASSIGNMENT
	 ***********************************/
	DDRC &= ~(1 << 0); //button
	PORTC |= (1 << 0);
	PORTC = 0xFF;
	
	
	DDRD = 0xFF;
	PORTD = 0b01111000;
	
	PORTD &= ~IR & ~LASER & ~UV;
	onState = 1;
	_delay_ms(10);
	
	DDRC |=  REDS|GREENS|BLUES;
	PORTC |= REDS|GREENS|BLUES;
	
	
	/***********************************
	 *             THE MAIN LOOP
	 * ********************************/
	
	uint8_t time = 0;
	uint8_t rtime = 0;
	uint8_t rtimeBuff = 70;
	uint8_t n = 0;
	
	uint8_t submode = 1;
	uint8_t submodeMax = 5;
	uint8_t submodeMemory[15];
	
	for(i=1;i<=15;i++)
	  submodeMemory[i] = 1;
	
	uint8_t r = 0;
	uint8_t g = 0;
	uint8_t b = 0;
	uint8_t r2 = 0;
	uint8_t count = 0;
	
	sei();
	
	//led_blink(2);
		
	
	uint8_t laser = 0;
	uint8_t uv = 0;
	
	for(;;)
	{
		_delay_ms(10);
		n = 0;
		
		if((PINC & (1 << 3)) != (1 << 3)) { // key pressed
			time++;
			n++;
		}
		else
			rtime++;
		
		if((time > 1) && (time < 40) && (n == 0)) {  // on|off
		  onState ^= 1;
		  time = 0;
		  
		  if (onState)
		    rtimeBuff = rtime;
		  rtime = 0;
		  if(onState && (rtimeBuff > 50))
		    for (i = 1; i <= 6; i++){
		      PORTC ^= GREENS|REDS;
		      PORTC ^= BLUES;
		      _delay_ms(80);
		    }
		}
		
		if((time == 110) && (n == 1)) { // change mode|on with white
		  if(onState) {
		    if(submode == submodeMax)
		      submode = 1;
		    else
		      submode++;
		  }
		  
		  else {
		    onState = 1;
		    mode = 1;
		    submode = submodeMemory[mode];
		    if(rtimeBuff > 50)
		      for (i = 1; i <= 6; i++){
			PORTC ^= GREENS|REDS;
			PORTC ^= BLUES;
			_delay_ms(80);
		      }
		    //laser = 0;
		    //uv = 0;
		  }
		}
		
		if (rtimeBuff < 50) { //double click
		    submodeMemory[mode] = submode;
		    if(mode == 15)
		      mode = 1;
		    else
		      mode++;
		    submode = submodeMemory[mode];
		  
		  rtimeBuff = 70;
		}
		
		if ((time > 110) && (n == 0))
		  time = 0;
		
		if (time == 251)
		  time--;
		
		if (rtime == 251)
		  rtime--;
		
		if(!(mode % 2)) {
		  strob = 1;
		  S = 20;
		  pin[0] = RED;
		  pin[1] = GREEN;
		  pin[2] = BLUE;
		  power[0] = 4;
		  power[1] = 4;
		  power[2] = 4;
		}
		else
		  strob = 0;
		
		if(!strob)
		  TIMSK |= (1 << OCIE2);
		else {
		  TIMSK &= ~(1 << OCIE2);
		  PORTD &= ~RED & ~GREEN & ~BLUE;
		}
		
		PORTC |= REDS;
		PORTC |= GREENS;
		PORTC |= BLUES;
		PORTD |= IR;
		
		r = 0;
		r2 = 0;
		b = 0;
		    
		switch (mode) {
		  case 1:  // white
		    submodeMax = 6;
		    
		    pin[0] = RED;
		    pin[1] = GREEN;
		    pin[2] = BLUE;
		    switch (submode){
		      case 1: // full power
			power[0] = 90;
			power[1] = 91;
			power[2] = 92;
			break;
		      case 2: // 0.1 lum
			power[0] = 4;
			power[1] = 5;
			power[2] = 6;
			break;
		      case 3: // 18 lum
			power[0] = 62;
			power[1] = 61;
			power[2] = 60;
			break;
		      case 4: // 25%
			power[0] = 17;
			power[1] = 18;
			power[2] = 19;
			
			break;
		      case 5: // 50%
			power[0] = 35;
			power[1] = 36;
			power[2] = 37;
			break;
		      case 6: // flash
			power[0] = 62;
			power[1] = 63;
			power[2] = 64;
			S = 50;
			strob = 1;
			break;
		    }
		    break;
		    
		  case 3:  // laser
		    submodeMax = 2;
		    
		    r2 = 2;
		    
		    power[0] = 1;
		    power[1] = 2;
		    power[2] = 3;
		    switch (submode){
		      case 1:
			laser = 0;
			break;
		      case 2:
			laser = 1;
			break;
		    }
		    break;
		    
		  case 5: // red & IR
		    submodeMax = 7;
		    
		    pin[0] = GREEN;
		    pin[1] = BLUE;
		    pin[2] = RED;
		    
		    switch (submode){
		      case 1: // 30% red
			power[0] = 1;
			power[1] = 2;
			power[2] = 19;
			break;
		      case 2: // 60% red
			power[0] = 1;
			power[1] = 2;
			power[2] = 62;
			break;
		      case 3: // 100% red
			power[0] = 1;
			power[1] = 2;
			power[2] = 91;
			break;
		      case 4: // 100% red + infra
			power[0] = 1;
			power[1] = 2;
			power[2] = 91;
			PORTD &= ~IR;
			r = 1;
			break;
		      case 5: // only infra
			power[0] = 1;
			power[1] = 2;
			power[2] = 3;
			PORTD &= ~IR;
			r = 1;
			break;
		    }
		    break;
		    
		  case 7: // UV
		      submodeMax = 2;
		    
		      power[0] = 1;
		      power[1] = 2;
		      power[2] = 3;
		      
		      b = 2;
		      switch (submode){
			case 1:
			  uv = 0;
			  break;
			case 2:
			  uv = 1;
			  break;
		      }
		      break;
		  case 9: // GREEN
		      submodeMax = 2;
		      pin[0] = RED;
		      pin[1] = BLUE;
		      pin[2] = GREEN;
		      switch (submode){
			case 1:
			  power[0] = 1;
			  power[1] = 2;
			  power[2] = 34;
			  break;
			case 2:
			  power[0] = 1;
			  power[1] = 2;
			  power[2] = 62;
			  break;
		      }
		      break;
		      
		  case 11: // blue
		      submodeMax = 2;
		      pin[0] = BLUE;
		      pin[1] = RED;
		      pin[2] = GREEN;
		      S = 128;
		      switch(submode) {
			case 1:
			  strob = 0;
			  power[0] = 1;
			  power[1] = 90;
			  power[2] = 91;
			  break;
			case 2:
			  strob = 1;
			  power[0] = 1;
			  power[1] = 90;
			  power[2] = 91;
			  break;
		      }
		      break;
		      
		  case 13:
		      submodeMax = 2;
		      pin[0] = GREEN;
		      pin[1] = RED;
		      pin[2] = BLUE;
		      S = 128;
		      switch(submode) {
			case 1:
			  strob = 0;
			  power[0] = 1;
			  power[1] = 2;
			  power[2] = 91;
			  break;
			case 2:
			  strob = 1;
			  power[0] = 1;
			  power[1] = 2;
			  power[2] = 91;
			  break;
		      }
		      break;

		case 15:
		      submodeMax = 2;
		      pin[0] = GREEN;
		      pin[1] = RED;
		      pin[2] = BLUE;
		      power[0] = 1;
		      power[1] = 2;
		      power[2] = 3;
		      g = 1;

		      switch(submode) {
			case 1:
			  PORTD &= ~IR;
			  r = 1;
			  
			  break;
			case 2:
			  
			  break;
		      }
		      break;
		}
		if (onState && laser && (mode != 15)) {
		  PORTD &= ~LASER;
		  r2 = 1;
		}
		else {
		  PORTD |= LASER;
		}
		
		if (onState && uv && (mode != 15)) {
		  PORTD &= ~UV;
		  b = 1;
		}
		else
		  PORTD |= UV;
		
		if(onState) {
		  if (b == 2)
		    if((count & 0b111111) > 32)
		      PORTC ^= BLUES;
		  if (b == 0)
		    PORTC |= BLUES;
		  if (b == 1)
		    PORTB &= ~BLUES;

		  if (r == 0)
		    PORTC |= REDS;
		  if (r == 1)
		    PORTC &= ~REDS;
		  
		  if (g == 0)
		    PORTC |= GREENS;
		  if (g == 1)
		    PORTC &= ~GREENS;
		  
		  if (r2 == 0)
		    PORTC |= REDS2;
		  if (r2 == 1)
		    PORTC &= ~REDS2;
		  if (r2 == 2)
		    if((count & 0b111111) > 32)
		      PORTC ^= REDS2;
		}
		else {
		  PORTC |= BLUES;
		  PORTC |= REDS;
		  PORTC |= REDS2;
		  PORTC |= GREENS;
		}
		
		count++;
	};

	return 0;
}